package com.example.sparkchaindemo;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.example.sparkchaindemo.adapter.SpinnerAdapter;
import com.example.sparkchaindemo.model.AisoundParams;
import com.example.sparkchaindemo.model.ErrorCode;
import com.example.sparkchaindemo.model.ParamInfo;
import com.example.sparkchaindemo.utils.AudioTrackManager;
import com.example.sparkchaindemo.utils.FileUtils;
import com.example.sparkchaindemo.utils.NumberUtils;
import com.iflytek.aikit.core.AeeEvent;
import com.iflytek.aikit.core.AiHandle;
import com.iflytek.aikit.core.AiHelper;
import com.iflytek.aikit.core.AiInput;
import com.iflytek.aikit.core.AiListener;
import com.iflytek.aikit.core.AiRequest;
import com.iflytek.aikit.core.AiResponse;
import com.iflytek.aikit.core.AiText;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 离线语音合成轻量版Aisound ece9d3c90
 * 调用流程：SDKinit-registerListener-start-write-end-engineUninit-SDKUninit
 */
public class AisoundActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener,
        AdapterView.OnItemSelectedListener {
    private final String TAG = "AEELog";
    private String ABILITYID = "ece9d3c90";

    Spinner sp_vcn;
    Button btn_start;
    EditText ed_input;
    AisoundParams aisoundParams = new AisoundParams();
    SeekBar sb_pitch, sb_speed, sb_volume;
    TextView tv_pitch_txt, tv_speed_txt, tv_volume_txt,tv_err_info;
    ProgressDialog mProgressDialog;
    //测试环境
    private AiHandle aiHandle;
    private String OUTPUT_DIR;
    private String outFileName;
    private int AEE_END = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aisound);
        OUTPUT_DIR = getResources().getString(R.string.workDir)+ "aisound" + File.separator + "output";
        AiHelper.getInst().registerListener(ABILITYID, aiRespListener);// 注册能力结果监听
        deleteAllOutPutDir();
        initView();
        initDialog();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //逆初始化
        AiHelper.getInst().engineUnInit(ABILITYID);
    }

    /**↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓SDK处理逻辑↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓**/
    /**
     * 结果监听回调
     */
    private AiListener aiRespListener = new AiListener(){

        @Override
        public void onResult(int handleID, List<AiResponse> list, Object usrContext) {
            if (null != list && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    byte[] bytes = list.get(i).getValue();
                    if (bytes == null) {
                        continue;
                    }
                    Log.d(TAG,"onResult:handleID:" + handleID + ":" + list.get(i).getKey());
                    makeOutPutDir();
                    FileUtils.writeFile(getOutFileName(handleID), bytes);
                }
            }
        }

        @Override
        public void onEvent(int handleID, int event, List<AiResponse> eventData, Object usrContext) {
            if (event == AeeEvent.AEE_EVENT_END.getValue()) {  // 引擎计算开始事件
                handler.sendEmptyMessage(AEE_END);
            } else if (event == AeeEvent.AEE_EVENT_PROGRESS.getValue()) {  // 引擎计算进度事件
                int pos = -1;
                int len = -1;
                for (int i = 0; i < eventData.size(); i++) {
                    AiResponse aiOutput = eventData.get(i);
                    if (aiOutput.getKey().equals("progress_pos")) {
                        pos = NumberUtils.bytesToInt(aiOutput.getValue());
                    } else if (aiOutput.getKey().equals("progress_len")) {
                        len = NumberUtils.bytesToInt(aiOutput.getValue());
                    }
                }
                Log.d(TAG, "handleID:" + handleID + "进度:" + pos + "/" + len);
            }
        }

        @Override
        public void onError(int handleID, int err, String msg, Object usrContext) {
            if (mProgressDialog.isShowing()) {
                mProgressDialog.dismiss();
            }
            String errInfo = "能力运行出错，错误码:"+err+",错误信息:"+msg;
            Log.d(TAG, errInfo);
            showInfo(errInfo);
        }
    };

    /**
     * 开始合成
     */
    public int runTTS(AisoundParams params, String text) {
        showInfo("");
        AiInput.Builder paramBuilder = AiInput.builder();
        paramBuilder.param("vcn", params.vcn); //必填参数,发音人：xiaoyan:中文 女 晓燕；xiaofeng:中文 男 晓峰；catherine:英文 女 catherine
        paramBuilder.param("textEncoding","UTF-8");//非必填,文本编码：GBK:GBK格式, UTF-8:UTF-8格式
        paramBuilder.param("pitch",params.pitch);//非必填,语调：最小值:0, 最大值:100
        paramBuilder.param("volume",params.volume);//非必填,音量：最小值:0, 最大值:100
        paramBuilder.param("speed",params.speed);//非必填,语速：最小值:0, 最大值:100
        //其他功能参数，请参考集成文档。
        aiHandle = AiHelper.getInst().start(ABILITYID, paramBuilder.build(), null);
        if (aiHandle.getCode() != 0) {
            String errinfo = "start失败:" + aiHandle.getCode();
            Log.d(TAG, errinfo);
            showInfo(errinfo);
            aiHandle = null;
            return ErrorCode.START_ERROR;
        }
        Log.d(TAG, "aiHandle.i:" + aiHandle.getI() + "," + aiHandle.getId());


        AiRequest.Builder dataBuilder = AiRequest.builder();
        //输入文本数据
        AiText input = AiText
                .get("text")
                .data(text) //text为String类型输入文本
                .valid();
        dataBuilder.payload(input);

        int ret = AiHelper.getInst().write(dataBuilder.build(), aiHandle);
        //ret 值为0 写入成功；非0失败，请参照文档中错误码部分排查
        if (ret != 0) {
            String errinfo = "write失败:" + ret;
            Log.d(TAG, errinfo);
            showInfo(errinfo);
            aiHandle = null;
            return ErrorCode.WRITE_ERROR;
        }
        return ErrorCode.SUCCESS;
    }
    private Handler handler = new Handler(new Handler.Callback() {
        /**
         * 合成结束，开始播报
         */
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            if (msg.what == AEE_END) {
                if(aiHandle != null){
                    int ret = AiHelper.getInst().end(aiHandle);
                    Log.d(TAG, "AIKit_End：" + ret);
                }
                String result = OUTPUT_DIR + File.separator + "OutPut_" + outFileName + ".pcm";
                Log.d(TAG, "输出的文件路径为:" + result);
                String info = "合成音频存放路径:"+result;
                showInfo(info);
                AudioTrackManager.getInstance().setSampleRate(AudioTrackManager.sampleRateType.SAMPLE_RATE_16k);//播报前先设置采样率
                AudioTrackManager.getInstance().startPlay(result);
                if (mProgressDialog.isShowing()) {
                    mProgressDialog.dismiss();
                }
            }
            return false;
        }
    });

/**↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑SDK处理逻辑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑**/
/**↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓Demo界面相关逻辑↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓**/
    /**
     * 状态展示弹框
     */
    private void initDialog() {
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setMessage("合成中，请稍后...");
    }

    /**
     * 初始化界面控件
     */
    private void initView() {
        sp_vcn = findViewById(R.id.aisound_sp_vcn);
        btn_start = findViewById(R.id.aisound_btn_start);
        ed_input = findViewById(R.id.aisound_ed_input);
        sb_pitch = findViewById(R.id.aisound_sb_pitch);
        sb_speed = findViewById(R.id.aisound_sb_speed);
        sb_volume = findViewById(R.id.aisound_sb_volume);
        tv_pitch_txt = findViewById(R.id.aisound_tv_pitch_txt);
        tv_speed_txt = findViewById(R.id.aisound_tv_speed_txt);
        tv_volume_txt = findViewById(R.id.aisound_tv_volume_txt);
        tv_err_info = findViewById(R.id.aisound_tv_showinfo);
        SpinnerAdapter vncAdapter = new SpinnerAdapter(this, AisoundParams.getVCN());
        sp_vcn.setAdapter(vncAdapter);
        sp_vcn.setOnItemSelectedListener(this);
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AudioTrackManager.getInstance().stopPlay();
                String text = ed_input.getText().toString();
                if (text != null && !"".equals(text)) {
                    mProgressDialog.show();
                    outFileName = String.valueOf(System.currentTimeMillis());
                    int result = runTTS(aisoundParams,
                            new String(text.getBytes(), StandardCharsets.UTF_8));
                    if (result != ErrorCode.SUCCESS) {
                        if (mProgressDialog.isShowing()) {
                            mProgressDialog.dismiss();
                        }
                    }
                } else {
                    Toast.makeText(AisoundActivity.this, "未输入要合成的文本", Toast.LENGTH_LONG).show();
                }
            }
        });
        sb_pitch.setOnSeekBarChangeListener(this);
        sb_speed.setOnSeekBarChangeListener(this);
        sb_volume.setOnSeekBarChangeListener(this);
    }

    /**
     * 获取合成结果音频文件路径
     */
    private String getOutFileName(int handleID) {
        return OUTPUT_DIR + File.separator + "OutPut_" + outFileName + ".pcm";
    }

    /**
     * 删除本地缓存的合成结果音频文件
     */
    private void deleteAllOutPutDir() {
        File dir = new File(OUTPUT_DIR);
        if (dir == null || !dir.exists() || !dir.isDirectory() || dir.listFiles() == null)
            return;
        for (File file : dir.listFiles()) {
            if (file.isFile())
                file.delete(); // 删除所有文件
        }
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 创建本地缓存的合成结果音频文件
     */
    private void makeOutPutDir() {
        File dir = new File(OUTPUT_DIR);
        if (dir != null && !dir.exists()) {
            dir.mkdirs();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        AudioTrackManager.getInstance().stopPlay();
    }
    /**
     * 信息显示
     */
    private void showInfo(String text){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv_err_info.setText(text+"\n");
            }
        });
    }
    /**
     * 获取语速，音量，语调控件结果
     */
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int id = seekBar.getId();
        if (id == R.id.aisound_sb_pitch) {
            aisoundParams.pitch = progress;
            tv_pitch_txt.setText(String.valueOf(progress));
        } else if (id == R.id.aisound_sb_speed) {
            aisoundParams.speed = progress;
            tv_speed_txt.setText(String.valueOf(progress));
        } else if (id == R.id.aisound_sb_volume) {
            aisoundParams.volume = progress;
            tv_volume_txt.setText(String.valueOf(progress));
        }
    }

    /**
     * 获取发音人，语种控件结果
     */
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (parent.getId() == R.id.aisound_sp_vcn) {
            aisoundParams.vcn = ((ParamInfo) sp_vcn.getAdapter().getItem(position)).value;
            ed_input.setText(aisoundParams.testTxt().get(position));
        }
    }
/**↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑Demo界面相关逻辑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑**/
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
}
